package com.atguigu.tingshu.order.listener;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.common.constant.RabbitConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AssertUtil;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.order.OrderDetail;
import com.atguigu.tingshu.model.order.OrderInfo;
import com.atguigu.tingshu.order.mapper.OrderDetailMapper;
import com.atguigu.tingshu.order.mapper.OrderInfoMapper;
import com.atguigu.tingshu.order.service.OrderInfoService;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.order.OrderDetailVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
@Slf4j
public class OrderMqListener {
    @Autowired
    OrderInfoService orderInfoService;
    @Autowired
    RabbitTemplate rabbitTemplate;
    @Autowired
    OrderDetailMapper orderDetailMapper;
    @Autowired
    UserInfoFeignClient userInfoFeignClient;


    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(value = RabbitConstant.PAYMENT_STATE_QUEUE , durable = "true"),
                    exchange = @Exchange(value = RabbitConstant.PAYMENT_EXCHANGE , type = "topic"),
                    key = {RabbitConstant.PAYMENT_STATE_RK}
            )
    })
    @SneakyThrows
    public void updateOrderStatus(Channel channel , Message message ,
                                  Map<String,String> map){
        //更新订单状态
        try {
            if(!CollectionUtils.isEmpty(map)){
                String orderNo = map.get("orderNo");
                String status = map.get("status");
                String orderStatus;
                String oldOrderStatus;
                switch (status){
                    case "1402":
                        //已支付
                        oldOrderStatus = SystemConstant.ORDER_STATUS_UNPAID;
                        OrderInfo orderInfo = orderInfoService.getOrderInfoByOrderNo(orderNo);
                        //保存交易记录：
                        UserPaidRecordVo userPaidRecordVo = new UserPaidRecordVo();
                        userPaidRecordVo.setUserId(orderInfo.getUserId());
                        userPaidRecordVo.setOrderNo(orderInfo.getOrderNo());
                        userPaidRecordVo.setItemType(orderInfo.getItemType());
                        //订单明细：  购买商品的id(vip id   专辑id 或者一组声音id)
                        List<Long> itemIds = orderInfo.getOrderDetailList()
                                .stream().map(OrderDetail::getItemId).collect(Collectors.toList());
                        userPaidRecordVo.setItemIdList(itemIds);
                        //  微信支付成功，保存交易记录时，支付已经完成  只需要保证交易记录一定保存成功即可
                        //   保存交易记录时 如果失败，发送告警邮件  让负责人人工介入处理！！
//                        Result savePaidRecordResult = userInfoFeignClient.savePaidRecords(userPaidRecordVo);
                        Result savePaidRecordResult = userInfoFeignClient.saveWxPaidRecords(userPaidRecordVo);
                        if(savePaidRecordResult==null || !savePaidRecordResult.getCode()
                                .equals(ResultCodeEnum.SUCCESS.getCode())){
                            log.error("保存交易记录失败：{}" , JSONObject.toJSONString(savePaidRecordResult));
                        }
//                        AssertUtil.resultAssert(savePaidRecordResult, ResultCodeEnum.DATA_ERROR);
                        orderStatus = SystemConstant.ORDER_STATUS_PAID;
                        break;
                    case SystemConstant.PAYMENT_STATUS_REFUND: //退款
                        orderStatus = "0904";
                        oldOrderStatus = SystemConstant.ORDER_STATUS_PAID;
                        break;
                    default:
                        orderStatus = SystemConstant.ORDER_STATUS_FAIL;
                        oldOrderStatus = SystemConstant.ORDER_STATUS_UNPAID;
                        break;
                }
                orderInfoService.update(Wrappers.lambdaUpdate(OrderInfo.class)
                        .eq(OrderInfo::getOrderNo , orderNo)
                        .eq(OrderInfo::getOrderStatus , oldOrderStatus)
                        .set(OrderInfo::getOrderStatus , orderStatus));

            }

            channel.basicAck(message.getMessageProperties().getDeliveryTag() , false);
        } catch (Exception e) {
            if(message.getMessageProperties().isRedelivered()){
                log.error("订单支付状态更新失败，消息内容：{}" , JSONObject.toJSONString(map));
                log.error(ExceptionUtils.getStackTrace(e));
                channel.basicReject(message.getMessageProperties().getDeliveryTag() , false);
            }else{
                log.warn("订单支付状态更新失败，尝试重试，消息内容：{}" , JSONObject.toJSONString(map));
                channel.basicNack(message.getMessageProperties().getDeliveryTag() , false,true);
            }
        }


    }

    //队列已存在 可以直接使用
    @RabbitListener(queues = {RabbitConstant.ORDER_DEAD_QUEUE})
    @SneakyThrows
    public void cancelOrder(Channel channel , Message message , String orderNo){
        //延迟关单业务：
        //如果orderNo的订单状态是默认状态(待支付) 更新订单状态为 取消
        try {
            orderInfoService.update(Wrappers.lambdaUpdate(OrderInfo.class)
                    .eq(OrderInfo::getOrderNo , orderNo)
                    .eq(OrderInfo::getOrderStatus , SystemConstant.ORDER_STATUS_UNPAID)
                    .set(OrderInfo::getOrderStatus , SystemConstant.ORDER_STATUS_CANCEL));

            //关单成功： 关闭微信支付交易记录
            rabbitTemplate.convertAndSend(
                    RabbitConstant.PAYMENT_EXCHANGE ,
                    RabbitConstant.PAYMENT_CLOSE_RK ,
                    orderNo
            );
            channel.basicAck(message.getMessageProperties().getDeliveryTag() , false);
        } catch (Exception e) {
            if(message.getMessageProperties().isRedelivered()){
                log.error("订单延迟关单失败，订单编号：{}" , orderNo);
                channel.basicReject(message.getMessageProperties().getDeliveryTag() , false);
                throw new RuntimeException(e);
            }else{
                log.warn("订单延迟关单失败，尝试重试，订单编号：{}" , orderNo);
                channel.basicNack(message.getMessageProperties().getDeliveryTag() , false,true);
            }
        }


    }


}
